#!/bin/bash
# Centos7 Rsync远程定时备份一键配置脚本
# 版本: 2.2
# 博客: https://blog.hx99.net
# 最后更新: 2025-04-27

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 全局变量
LOG_FILE="/var/log/rsync_backup.log"
RSYNC_USER="rsync"
DEFAULT_PASSWORD="Backup@2023"

# 打印彩色欢迎信息
echo -e "${GREEN}"
echo "============================================"
echo "      CentOS7 Rsync远程定时备份一键配置脚本       "
echo "============================================"
echo -e "${NC}"
echo -e "${YELLOW}▌核心功能：${NC}"
echo -e "  ${GREEN}➤${NC} 全自动配置 ${BLUE}服务端${NC}(接收端)/${BLUE}客户端${NC}(发送端)"
echo -e "  ${GREEN}➤${NC} 智能交互设计，新手友好且高效可靠"
echo -e "  ${GREEN}➤${NC} 首次运行自动验证同步功能"
echo -e "  ${GREEN}➤${NC} 详细日志记录（${BLUE}${LOG_FILE}${NC}）"
echo -e "  ${GREEN}➤${NC} 支持自定义定时任务"
echo ""
echo -e "${RED}▌重要提示：${NC}"
echo -e "  ${YELLOW}⚠${NC} 必须${RED}先配置服务端${NC}，再配置客户端"
echo -e "  ${YELLOW}⚠${NC} 确保防火墙放行${RED}873${NC}端口"
echo -e "  ${YELLOW}⚠${NC} 如输入的备份目录不存在，将自动创建"
echo -e "  ${YELLOW}⚠${NC} SELinux问题请执行：${GREEN}setsebool -P rsync_full_access on${NC}"
echo -e "  ${YELLOW}⚠${NC} 大文件备份建议使用${BLUE}screen/tmux${NC}"
echo -e "  ${YELLOW}⚠${NC} 需${RED}root权限${NC}",适用于${RED}CentOS7${NC},其它系统未测试！
echo -e "${BLUE}▌技术支持：${NC}http://blog.hx99.net  https://gitee.com/cncsrf/rsync-remote-backup"
echo "============================================"
echo ""

# 检查root权限
if [ "$(id -u)" -ne 0 ]; then
    echo -e "${RED}错误：请使用root用户运行此脚本！${NC}" >&2
    exit 1
fi

# 选择模式：服务端 or 客户端
echo -e "${BLUE}请选择配置模式：${NC}"
echo -e "1) 服务端（接收备份数据）"
echo -e "2) 客户端（发送备份数据）"
read -p "输入数字 (1/2): " MODE

# 验证模式输入
if [[ ! "$MODE" =~ ^[12]$ ]]; then
    echo -e "${RED}错误：请输入1或2！${NC}" >&2
    exit 1
fi

# 配置服务端
if [ "$MODE" -eq 1 ]; then
    echo -e "${GREEN}正在配置Rsync服务端...${NC}"
    
    # 安装rsync
    if ! command -v rsync &> /dev/null; then
        echo -e "${BLUE}安装rsync...${NC}"
        yum install -y rsync || { echo -e "${RED}安装失败！${NC}"; exit 1; }
    fi

    # 输入备份目录
    read -p "请输入服务端备份存储目录 (默认: /opt/data_bak): " BACKUP_DIR
    BACKUP_DIR=${BACKUP_DIR:-/opt/data_bak}
    mkdir -p "$BACKUP_DIR" || { echo -e "${RED}目录创建失败！${NC}"; exit 1; }
    chmod 750 "$BACKUP_DIR"
    echo -e "${GREEN}备份目录已设置: ${BACKUP_DIR}${NC}"

    # 输入认证密码
    while true; do
        read -p "设置rsync认证密码 (默认: ${DEFAULT_PASSWORD}): " PASSWORD
        PASSWORD=${PASSWORD:-$DEFAULT_PASSWORD}
        
        # 密码复杂度检查
        if [ -z "$PASSWORD" ]; then
            echo -e "${RED}错误：密码不能为空！${NC}"
            continue
        fi
        if [ "${#PASSWORD}" -lt 4 ]; then
            echo -e "${YELLOW}警告：密码长度建议至少4位字符！继续？(y/n): ${NC}"
            read -p "" CONFIRM
            [[ "$CONFIRM" =~ ^[Yy]$ ]] || continue
        fi
        break
    done

    # 配置rsyncd.conf
    echo -e "${BLUE}生成 /etc/rsyncd.conf ...${NC}"
    cat > /etc/rsyncd.conf <<EOF
uid = root
gid = root
use chroot = no
max connections = 20
timeout = 300
pid file = /var/run/rsyncd.pid
log file = /var/log/rsyncd.log

[data_backup]
path = $BACKUP_DIR
comment = Backup Directory
read only = no
auth users = $RSYNC_USER
secrets file = /etc/rsyncd.secrets
EOF

    # 配置密码文件
    echo "$RSYNC_USER:$PASSWORD" > /etc/rsyncd.secrets
    chmod 600 /etc/rsyncd.secrets

    # 启动服务
    systemctl enable --now rsyncd
    systemctl status rsyncd --no-pager

    echo -e "${GREEN}服务端配置完成！${NC}"
    echo -e "${YELLOW}客户端连接命令示例：${NC}"
    echo -e "rsync -avz --delete /your/local/path/ ${RSYNC_USER}@$(hostname -I | awk '{print $1}')::data_backup --password-file=/etc/rsyncd.secrets"

# 配置客户端
else
    echo -e "${GREEN}正在配置Rsync客户端...${NC}"

    # 检查服务端是否已配置
    echo -e "${YELLOW}请确保服务端已提前配置完成！${NC}"
    read -p "按任意键继续..." -n 1 -r

    # 安装rsync
    if ! command -v rsync &> /dev/null; then
        echo -e "${BLUE}安装rsync...${NC}"
        yum install -y rsync || { echo -e "${RED}安装失败！${NC}"; exit 1; }
    fi

    # 输入服务端IP
    while true; do
        read -p "请输入Rsync服务端IP地址: " SERVER_IP
        if [[ -z "$SERVER_IP" ]]; then
            echo -e "${RED}错误：IP地址不能为空！${NC}"
            continue
        fi
        if ! ping -c 1 "$SERVER_IP" &> /dev/null; then
            echo -e "${YELLOW}警告：无法ping通服务端IP，请检查网络！继续？(y/n): ${NC}"
            read -p "" CONFIRM
            [[ "$CONFIRM" =~ ^[Yy]$ ]] || continue
        fi
        break
    done

    # 输入本地备份目录（带默认值和自动创建）
    DEFAULT_LOCAL_DIR="/var/www"
    while true; do
        read -p "请输入需要备份的本地目录 (默认: ${DEFAULT_LOCAL_DIR}): " LOCAL_DIR
        LOCAL_DIR=${LOCAL_DIR:-$DEFAULT_LOCAL_DIR}
        
        if [ ! -d "$LOCAL_DIR" ]; then
            echo -e "${YELLOW}目录不存在，将自动创建 ${LOCAL_DIR} ...${NC}"
            mkdir -p "$LOCAL_DIR" || { 
                echo -e "${RED}目录创建失败！${NC}"
                echo -e "${YELLOW}是否尝试其他目录？(y/n): ${NC}"
                read -p "" CONFIRM
                [[ "$CONFIRM" =~ ^[Yy]$ ]] || exit 1
                continue
            }
            echo -e "${GREEN}已创建目录: ${LOCAL_DIR}${NC}"
            
            # 创建测试文件
            echo "This is a test file created by rsync setup script" > "${LOCAL_DIR}/sync_test_file.txt"
            echo -e "${GREEN}已创建测试文件：${LOCAL_DIR}/sync_test_file.txt${NC}"
        fi
        break
    done

    # 输入密码
    read -p "输入服务端rsync密码 (默认: ${DEFAULT_PASSWORD}): " PASSWORD
    PASSWORD=${PASSWORD:-$DEFAULT_PASSWORD}
    echo "$PASSWORD" > /etc/rsyncd.secrets
    chmod 600 /etc/rsyncd.secrets

    # 友好化定时任务设置
    while true; do
        echo -e "${BLUE}请选择备份频率：${NC}"
        echo "1) 每天凌晨2点（默认）"
        echo "2) 每天指定小时（如输入17表示每天17点）"
        echo "3) 自定义cron表达式（高级用户）"
        read -p "输入数字 (1/2/3): " CRON_CHOICE

        case $CRON_CHOICE in
            1) 
                CRON_TIME="0 2 * * *"
                break
                ;;
            2)
                read -p "请输入每天执行的小时 (0-23): " HOUR
                if [[ "$HOUR" =~ ^[0-9]$|^1[0-9]$|^2[0-3]$ ]]; then
                    CRON_TIME="0 $HOUR * * *"
                    break
                else
                    echo -e "${RED}无效时间，请重新输入！${NC}"
                fi
                ;;
            3)
                read -p "请输入自定义cron表达式 (如 '0 3 * * *'): " CRON_TIME
                if [[ "$CRON_TIME" =~ ^[0-9*]+(\s+[0-9*]+){4}$ ]]; then
                    break
                else
                    echo -e "${RED}无效表达式，请参考cron语法！${NC}"
                fi
                ;;
            *)
                echo -e "${RED}无效选择，请重新输入！${NC}"
                ;;
        esac
    done

    # 生成备份脚本
    BACKUP_SCRIPT="/opt/rsync_backup.sh"
    cat > "$BACKUP_SCRIPT" <<EOF
#!/bin/bash
echo "====== 备份开始 \$(date) =====" >> $LOG_FILE
rsync -avz --delete "$LOCAL_DIR/" ${RSYNC_USER}@${SERVER_IP}::data_backup --password-file=/etc/rsyncd.secrets >> $LOG_FILE 2>&1
if [ \$? -eq 0 ]; then
    echo -e "同步状态: \033[0;32m成功\033[0m" >> $LOG_FILE
    echo "传输详情:" >> $LOG_FILE
    grep -E 'sent|total size' $LOG_FILE | tail -2 >> $LOG_FILE
else
    echo -e "同步状态: \033[0;31m失败\033[0m (错误码: \$?)" >> $LOG_FILE
fi
echo "====== 备份完成 \$(date) =====" >> $LOG_FILE
EOF

    chmod +x "$BACKUP_SCRIPT"
    
    # 清除旧定时任务并添加新任务
    TEMP_CRON=$(crontab -l 2>/dev/null | grep -v "$BACKUP_SCRIPT")
    echo "$TEMP_CRON" | crontab -
    (crontab -l 2>/dev/null; echo "$CRON_TIME $BACKUP_SCRIPT") | crontab -

    # 首次立即执行测试（严格验证）
    echo -e "${GREEN}正在执行首次同步测试...${NC}"
    rm -f "$LOG_FILE" 2>/dev/null
    bash "$BACKUP_SCRIPT"

    # 验证同步结果
    if grep -q "同步状态: .*成功" "$LOG_FILE"; then
        echo -e "${GREEN}同步验证成功！服务端应已收到以下文件：${NC}"
        grep -A 5 "sent" "$LOG_FILE"
        echo -e "\n${YELLOW}定时任务已添加：${NC}"
        crontab -l | grep "$BACKUP_SCRIPT"
    else
        echo -e "${RED}同步失败！请检查以下日志：${NC}"
        tail -n 10 "$LOG_FILE"
        echo -e "${YELLOW}可能原因：${NC}"
        echo "1. 服务端未运行"
        echo "2. 密码不正确"
        echo "3. 网络连接问题"
        exit 1
    fi
fi

echo -e "${GREEN}详细日志请查看: ${LOG_FILE}${NC}"